﻿using System;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace WindowsGame1.Text.RealText
{
    public class Login
    {
        #region Fields( _input, _handle, _blinkDelay, _blinkTimer, blink, _cursorPosition, _displayCursor )

        static private RealText _input;
        static private IntPtr _handle;
        public string Text;
        SpriteFont Font;

        private int _blinkTimer;
        private bool _blink;
        private Vector2 _cursorPosition;
        private bool _displayCursor;

        #endregion

        #region Another Fields
        private bool usr;
        public string username;
        public string pass;
        #endregion

        #region Properties( HasFocus, EnterPressed, DisplayCursor, CursorString, CursorPosition, CursorOffset

        /// <summary>
        /// returns bool that indicates wheter this textbox is hooked into the windows keyboard events. 
        /// </summary>
        public bool HasFocus { get; protected set; }
        /// <summary>
        /// returns bool that indicates wheter Enter is pressed. (current implementation Blurs textbox when enter
        /// is pressed.)
        /// </summary>
        public bool EnterPressed { get; protected set; }

        /// <summary>
        /// Property to set wheter or not a textbox should display a cursor. 
        /// </summary>
        public bool DisplayCursor { get; set; }
        /// <summary>
        /// This is the string used as a cursor. (Future implemenations may allow for animated sprite)
        /// </summary>
        public string CursorString { get; set; }
        /// <summary>
        /// Property allowing position of cursor to be set, it is calculated internally so it is a protected property. 
        /// </summary>
        protected Vector2 CursorPosition { get { return this._cursorPosition; } set { this._cursorPosition = value; } }
        /// <summary>
        /// Offset value to add to Cursors Position to allow for alignment tweeks. 
        /// </summary>
        public Vector2 CursorOffset { get; set; }
        /// <summary>
        /// BlinkDelay is a Property to set the interval at which the cursor is blinked.
        /// </summary>
        public int BlinkDelay { get; set; }

        #endregion

        #region Constructor, Update, Draw

        /// <summary>
        /// Creates a textbox with default settings.
        /// BlinkDelay = 350 milliseconds
        /// CursorString = "_"
        /// DisplayCursor = true
        /// CursorOffset = (0,0)
        /// </summary>
        /// <param name="game">Instance of Game class</param>
        /// <param name="assetName">Name of the background Texture2D to be loaded for textbox</param>
        /// <param name="fontName">Name of the font to used in the textbox</param>
        public Login(omfg game, SpriteFont fontName )
        {
            // check to see if a handle has already been assigned.
            if (Login._handle != null)
            {
                // no window handle has been previously assigned so set handle from the game parameter. 
                Login._handle = game.Window.Handle;
            }
            this.EnterPressed = false;
            this.BlinkDelay = 350;
            this._blinkTimer = 0;
            this._blink = false;
            HasFocus = true;
            this.CursorOffset = Vector2.Zero;
            this.CursorString = "_";
            this.DisplayCursor = true;
            this._displayCursor = true;
            Font = fontName;
            usr = true;
            username = String.Empty;
            pass = String.Empty;
        }

        public void Reseta()
        {
            usr = true;
            username = String.Empty;
            pass = String.Empty;
            _input.clearBuffer();
        }

        public char Update(GameTime gameTime)
        {
            this._blinkTimer += gameTime.ElapsedGameTime.Milliseconds;
            if (this._blinkTimer > this.BlinkDelay)
            {
                this._blink = !this._blink;
                this._blinkTimer = 0;
            }

            if (this.Text == String.Empty)
            {
               // Text = this.parseText(this.Text);
            }
                if (_input == null)
                {
                    SetTextInput();
                } 

                // check to see if the EnterKey was pressed. 
                if (_input.EnterKey)
                {
                    if (usr == true)
                    {
                        usr = false;
                        Text = String.Empty;
                    }
                    else
                    {
                        return 'j';
                    }
                    // blur this text box and set EnterPressed Property of this Textbox. 
                    this.EnterPressed = true;
                }
                else
                {
                    // Enter has not been pressed to process the windows events if present. 
                    // poll the keys from event buffer and add it to the Text Property. 
                    this.Text += _input.Buffer;
                    // clear buffer so next poll does not contain characters from previous poll. 
                    _input.clearBuffer();
                    // check to see if backspace was pressed.
                    if (_input.BackSpace)
                    {
                        // ensure Text Property is not empty. 
                        if (this.Text.Length > 0)
                        {
                            // set Text Property to itself minus the last character. 
                            this.Text = this.Text.Substring(0, this.Text.Length - 1);
                        }
                    }
                }
                if (usr == true)
                {
                    username = Text;
                }
                else
                {
                    pass = Text;
                }
            //}
            return 'l';
        }

        public void Draw(SpriteBatch spriteBatch)
        {

            // make sure textbox has focus, that the cursor is suppose to be displayed, and if cursor is current blinked.
            if (this._displayCursor && this._blink)
            {
                // check to see if Text is empty. 
                if (this.Text == String.Empty)
                {
                    // corrects cursor position for empty Text Property when word wrapping is disabled. 
                    this._cursorPosition = this.Font.MeasureString(" ");
                }
                else
                {
                    this._cursorPosition = this.Font.MeasureString(this.Text);// * 14;
                }
                // draws the cursor. 
                if (usr == true)
                {
                    spriteBatch.DrawString(Font, this.CursorString, new Vector2(400 + (username.Length * 13), 768 / 2), Color.Black);
                }
                else
                {
                    spriteBatch.DrawString(Font, this.CursorString, new Vector2(400 + (pass.Length * 13), 768 / 2 + 20 ), Color.Black);
                }
            }
            string user = "username:";
            string password = "password:";
            spriteBatch.DrawString(Font, user, new Vector2(400 - (user.Length * 14), 768 / 2), Color.Black);
            spriteBatch.DrawString(Font, password, new Vector2(400 - (user.Length * 14), 768 / 2 + 20), Color.Black);
            spriteBatch.DrawString(Font, username, new Vector2(400, 768 /2), Color.Black);
            string xpto = null;
            for (int a = 0; a < pass.Length; a++)
            {
                xpto += '*';
                spriteBatch.DrawString(Font, xpto, new Vector2(400, 768 / 2 + 20), Color.Black);
            }
        }

        #endregion

        #region Functions
        private void SetTextInput()
        {
            // ensures that textbox is not already hooked before creating a new hook. 
            if (_input == null)
            {
                _input = new RealText(_handle);
            }
        }
        /// <summary>
        /// Hooks the textbox into the windows keyboard events
        /// </summary>
        public void SetRealText()
        {
            // ensures that textbox is not already hooked before creating a new hook. 
            if (_input == null)
            {
                _input = new RealText(_handle);
            }
        }

        /// <summary>
        /// Removes the Focus of the textbox and Disposes the Hook to the windows keyboard events. 
        /// </summary>
        public void Blur()
        {
            this.HasFocus = false;
            _input.Dispose();
            _input = null;
        }

        protected String parseText(String text)
        {
            // used to determine if programmer explicitly set the DisplayCursor to false. 
            if (this.DisplayCursor)
            {
                // programmer set to true so set to display cursor flag to true. 
                this._displayCursor = true;
            }
            else
            {
                // programmer set to false, so do not display cursor at all. 
                this._displayCursor = false;
            }
            String line = String.Empty;
            String returnString = String.Empty;
            // breaks the text string into an array that contains each word in the string as seperate element.  
            String[] wordArray = text.Split(' ');
            // Added line to work with my Textbox implementation, instremental in my Clipping algorithim. 
            Vector2 textSafeArea = new Vector2(90,14);

            // KLUDGE: with out this I can not adjust for cursor position, offsets to wierd position
            //         feel free to explore and fix. 
            bool test = false;

            foreach (String word in wordArray)
            {
                // Checks to see if the width of the line exceeds text safe area's width, 
                // does this by piecing together the words one at a time and checking to see if
                // that current line width + new word width exceeds length. 
                // Modified this line slightly from original by adding the .X to MeasureString(line + word) as 
                // it was only nessisary to check against width. 
                if (this.Font.MeasureString(line + word).X > textSafeArea.X)
                {
                    // Added this line to clip along the y axis of the text safe area.  
                    if ((this.Font.MeasureString(returnString).Y + this.Font.LineSpacing) > textSafeArea.Y)
                    {
                        // the words from this point can not be seen, so cursor is outside of text safe area, set 
                        // display cursor flag to false. 
                        this._displayCursor = false;
                        // breaks out of the loop ending the parsing.
                        break;
                    }
                    // adds the line with the '/n' added to the return string. 
                    returnString = returnString + line + '\n';

                    // KLUDGE: with out this I can not adjust for cursor position, offsets to wierd position
                    //         feel free to explore and fix. 
                    test = true;
                    // resets the line to empty so a new line can be constructed with no contamination. 
                    line = String.Empty;
                }

                // add the word to the current line as it has not exceed the width of the text safe area. 
                line = line + word + ' ';
            }
            this._cursorPosition.X = this.Font.MeasureString(line).X;

            // KLUDGE: with out the ( test ? var : var ) I can not adjust for cursor position, offsets to wierd position
            //         feel free to explore and fix. 
            this._cursorPosition.Y = (this.Font.MeasureString(returnString).Y + (test ? 0.0f : (float)this.Font.LineSpacing));
            // parsing complete return the constructed string. 
            return returnString + line;
        }
        #endregion
    }
}
